<?php

namespace app\api\controller;

use app\admin\model\Config;
use app\api\service\VolcengineService;
use app\common\controller\ApiBase;
use app\Constant\ApiConstant;
use app\model\ChatLog;
use app\api\service\DeepSeekService;
use GuzzleHttp\Client;
use think\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\exception\DbException;
use util\Logger;

set_time_limit(3600);
ignore_user_abort(true);

class Chat extends ApiBase
{

    public function test()
    {
        $uuid = genRandomString(16);
        $this->assign('uuid', $uuid);
        return $this->fetch('test');
    }

    public function send_web()
    {
        $uuid = genRandomString(16);
        $this->assign('uuid', $uuid);
        return $this->fetch('send');
    }

    /**
     * 创建聊天对话
     * @return \think\response\Json
     */
    public function create()
    {
        $ai_gold = Config::where('name', 'ai_gold')->value('value');
        $uuid    = genRandomString(16);
        return $this->callback(ApiConstant::SUCCESS, 'success', [
            'uuid'    => $uuid,
            'title'   => '新对话',
            'ai_gold' => intval($ai_gold),
        ]);
    }

    public function lists()
    {
        $user_id = \app\model\User::where('token', $this->token)->value('id');
        $lists   = ChatLog::field('id, title, uuid')
            ->where('user_id', $user_id)
            ->where('role', 'user')
            ->order('id', 'desc')
            ->select()
            ->toArray();
        $res     = $add = [];
        foreach ($lists as $item) {
            if (!in_array($item['uuid'], $add)) {
                $add[] = $item['uuid'];
                $res[] = $item;
            }
        }
        return $this->callback(ApiConstant::SUCCESS, 'success', $res);
    }

    public function stream()
    {
        $params  = $this->request->post();
        $message = $params['message'];
        if (empty($message)) {
            return $this->callback(ApiConstant::FAILURE, 'message', '请输入内容');
        }
        if (strlen($message) > 1000) {
            return $this->callback(ApiConstant::FAILURE, 'message', '内容不能超过1000个字符');
        }

        $user = \app\model\User::field('id, vip_expire_time, chat_count')->where('token', $this->token)->find();
        if (empty($user)) {
            return $this->callback(ApiConstant::FAILURE, '用户未登录');
        }
        $user        = $user->getData();
        $ai_vip_free = intval(Config::where('name', 'ai_vip_free')->value('value')); //会员是否免费使用
        $is_vip      = 0; //是否会员
        if (!$ai_vip_free && $user['chat_count'] < 1) {
            return $this->callback(ApiConstant::FAILURE, '请开通会员或兑换对话次数');
        } else {
            if (time() > $user['vip_expire_time']) {
                if ($user['chat_count'] < 1) {
                    return $this->callback(ApiConstant::FAILURE, '请开通会员或兑换对话次数');
                }
            } else {
                $is_vip = 1;
            }
        }

        $user_id = $user['id'];
        //聊天标识
        $uuid = !empty($params['uuid']) ? $params['uuid'] : '';
        if (empty($uuid)) {
            return $this->callback(ApiConstant::FAILURE, '请先创建对话');
        }
        $history      = ChatLog::field('id, title, uuid, content, role')->where('user_id', $user_id)
            ->where('uuid', $uuid)
            ->select()
            ->toArray();
        $history_data = array_map(function ($item) {
            return [
                'role'    => $item['role'],
                'content' => $item['content'],
            ];
        }, $history);

        // 设置流式响应头
        header('Content-Type: text/event-stream');
        header('Cache-Control: no-cache');
        header('X-Accel-Buffering: no'); // 禁用Nginx缓冲

        $chat_title = $history[0]['title'] ?? '';
        if (empty($chat_title)) {
            $chat_title = $this->truncateString($message, 15);
        }
        // 保存用户消息
        ChatLog::addRecord($user_id, $uuid, $message, 'user', $chat_title);

        try {
            $model = !empty($params['model']) ? $params['model'] : 1;
            if ($model == 1) {
                $service = new DeepSeekService();
            } else {
                $service = new VolcengineService();
            }
            $messages     = array_merge(
                $history_data,
                [['role' => 'user', 'content' => $message]]
            );
            $fullResponse = '';
            $lastPing     = time(); // 添加心跳计时器

            $service->streamChatCompletion($messages, function ($content, $end, $reasoning_content = null) use (&$fullResponse, &$lastPing) {
                // 每3秒发送一次数据库心跳
                if (time() - $lastPing > 3) {
                    try {
                        \think\Db::connect()->query('SELECT 1');
                    } catch (\Exception $e) {
                        \think\Db::connect(true); // 强制重新连接
                    }
                    $lastPing = time();
                }

                if ($reasoning_content) {
                    echo json_encode(['content' => $reasoning_content, 'event' => 'thinking']) . "\n\n";
                }
                if ($content) {
                    $fullResponse .= $content;
                    echo json_encode(['content' => $content, 'event' => 'content']) . "\n\n";
                }
                ob_flush();
                flush();
            });
            // 确保所有缓冲区都被刷新
            ob_end_flush();

            // 保存前双重保障数据库连接
            try {
                \think\Db::connect()->query('SELECT 1');
            } catch (\Exception $e) {
                \think\Db::connect(true);
            }
            //不是会员扣减次数
            if (!$is_vip) {
                \app\model\User::where('id', $user_id)->update(['chat_count' => $user['chat_count'] - 1]);
            }
            // 保存AI消息
            ChatLog::addRecord($user_id, $uuid, $fullResponse, 'assistant', $chat_title);
        } catch (\Exception $e) {
            \think\Db::connect(true); // 异常时强制重连
            Logger::error('流式请求异常: ' . $e->getMessage());
            echo json_encode(['content' => '请求超时', 'event' => 'content']) . "\n\n";
        }
        exit;
    }

    /**
     * 截取字符串（支持多字节字符）
     * @param string $str 原始字符串
     * @param int $length 截取长度
     * @param string $encoding 字符编码，默认UTF-8
     * @return string
     */
    public function truncateString(string $str, int $length, string $encoding = 'UTF-8')
    {
        if (mb_strlen($str, $encoding) <= $length) {
            return $str;
        }
        return mb_substr($str, 0, $length, $encoding);
    }

    public function send()
    {
        $params  = $this->request->post();
        $message = $params['message'];
        if (empty($message)) {
            return $this->callback(ApiConstant::FAILURE, 'message', '请输入内容');
        }
        if (strlen($message) > 1000) {
            return $this->callback(ApiConstant::FAILURE, 'message', '内容不能超过1000个字符');
        }

        try {
            $user = \app\model\User::field('id, vip_expire_time')->where('token', $this->token)->find();
            if (empty($user)) {
                return $this->callback(ApiConstant::FAILURE, '用户未登录');
            }
            $user    = $user->getData();
            $user_id = $user['id'];
            //聊天标识
            $uuid = !empty($params['uuid']) ? $params['uuid'] : '';
            if (empty($uuid)) {
                $uuid = ChatLog::where('user_id', $user_id)->value('uuid') ?: genRandomString(16);
            }
            $history      = ChatLog::where('user_id', $user_id)
                ->where('uuid', $uuid)
                ->select()
                ->toArray();
            $history_data = array_map(function ($item) {
                return [
                    'role'    => $item['role'],
                    'content' => $item['content'],
                ];
            }, $history);

            // 保存用户消息
            ChatLog::addRecord($user_id, $uuid, $message, 'user');
            $ai_type = Config::where('name', 'ai_type')->value('value') ?: 1;
            switch ($ai_type) {
                case 2:
                    $service = new VolcengineService();
                    break;
                default:
                    $service = new DeepSeekService();
            }

            // 构建消息历史
            $messages = array_merge(
                $history_data,
                [['role' => 'user', 'content' => $message]]
            );
            $response = $service->createChatCompletion($messages);
            if (!$response['success']) {
                return $this->callback(ApiConstant::FAILURE, 'message', '请求超时');
            }
            // 保存AI回复
            ChatLog::addRecord($user_id, $uuid, $response['data'], 'assistant');
            return $this->callback(ApiConstant::SUCCESS, 'data', $response['data']);
        } catch (Exception $e) {
            return $this->callback(ApiConstant::FAILURE, 'success', '请求超时');
        }
    }

    public function exchange()
    {
        $user    = \app\model\User::field('id, gold, chat_count')->where('token', $this->token)->find();
        $ai_gold = Config::where('name', 'ai_gold')->value('value');
        if ($user['gold'] < $ai_gold) {
            return $this->callback(ApiConstant::FAILURE, '兑换失败，K币不足');
        }
        $res = \app\model\User::where('id', $user['id'])->update([
            'gold'       => $user['gold'] - $ai_gold,
            'chat_count' => $user['chat_count'] + 1
        ]);
        if ($res) {
            return $this->callback(ApiConstant::SUCCESS, '兑换成功');
        } else {
            return $this->callback(ApiConstant::FAILURE, '兑换失败');
        }
    }

    public function update()
    {
        $uuid  = $this->request->post('uuid');
        $title = $this->request->post('title');
        $res   = ChatLog::where('uuid', $uuid)->update(['title' => $title]);
        if ($res) {
            return $this->callback(ApiConstant::SUCCESS, '操作成功');
        } else {
            return $this->callback(ApiConstant::FAILURE, '操作失败');
        }
    }

    public function info()
    {
        $user = \app\model\User::field('id')->where('token', $this->token)->find();
        if (empty($user)) {
            return $this->callback(ApiConstant::NO_LOGIN, '用户未登录');
        }
        $uuid  = $this->request->param('uuid');
        $lists = ChatLog::field('id, uuid, role, content')->where('user_id', $user['id'])
            ->where('uuid', $uuid)
            ->select()->toArray();
        return $this->callback(ApiConstant::SUCCESS, 'success', $lists);
    }

    public function delete()
    {
        $uuid = $this->request->post('uuid');
        $res  = ChatLog::where('uuid', $uuid)->delete();
        if ($res) {
            return $this->callback(ApiConstant::SUCCESS, '操作成功');
        } else {
            return $this->callback(ApiConstant::FAILURE, '操作失败');
        }
    }

    public function test_send()
    {
        $params  = $this->request->post();
        $message = $params['message'];
        if (empty($message)) {
            return $this->callback(ApiConstant::FAILURE, 'message', '请输入内容');
        }
        if (strlen($message) > 1000) {
            return $this->callback(ApiConstant::FAILURE, 'message', '内容不能超过1000个字符');
        }

        $user = \app\model\User::field('id, vip_expire_time, chat_count')->where('chat_count', '>', 0)->find();
        if (empty($user)) {
            return $this->callback(ApiConstant::FAILURE, '用户未登录');
        }
        $user   = $user->getData();
        $is_vip = 0;
        if (time() > $user['vip_expire_time']) {
            if ($user['chat_count'] < 1) {
                return $this->callback(ApiConstant::FAILURE, '请开通会员或兑换对话次数');
            }
        } else {
            $is_vip = 1;
        }
        $user_id = $user['id'];
        //聊天标识
        $uuid = !empty($params['uuid']) ? $params['uuid'] : '';
        if (empty($uuid)) {
            return $this->callback(ApiConstant::FAILURE, '请先创建对话');
        }
        $history      = ChatLog::field('id, title, uuid, content, role')->where('user_id', $user_id)
            ->where('uuid', $uuid)
            ->select()
            ->toArray();
        $history_data = array_map(function ($item) {
            return [
                'role'    => $item['role'],
                'content' => $item['content'],
            ];
        }, $history);
        $chat_title   = $history[0]['title'] ?? '';
        if (empty($chat_title)) {
            $chat_title = $this->truncateString($message, 20);
        }

        // 设置流式响应头
        header('Content-Type: text/event-stream');
        header('Cache-Control: no-cache');
        header('X-Accel-Buffering: no'); // 禁用Nginx缓冲


        // 保存用户消息
        ChatLog::addRecord($user_id, $uuid, $message, 'user', $chat_title);

        try {
            $model = !empty($params['model']) ? $params['model'] : 1;
            if ($model == 1) {
                $service = new DeepSeekService();
            } else {
                $service = new VolcengineService();
            }
            $messages     = array_merge(
                $history_data,
                [['role' => 'user', 'content' => $message]]
            );
            $fullResponse = '';
            $lastPing     = time(); // 添加心跳计时器

            $service->streamChatCompletion($messages, function ($content, $end, $reasoning_content = null) use (&$fullResponse, &$lastPing) {
                // 每3秒发送一次数据库心跳
                if (time() - $lastPing > 3) {
                    try {
                        \think\Db::connect()->query('SELECT 1');
                    } catch (\Exception $e) {
                        \think\Db::connect(true); // 强制重新连接
                    }
                    $lastPing = time();
                }

                if ($reasoning_content) {
                    echo json_encode(['content' => $reasoning_content, 'event' => 'thinking']) . "\n\n";
                }
                if ($content) {
                    $fullResponse .= $content;
                    echo json_encode(['content' => $content, 'event' => 'content']) . "\n\n";
                }
                ob_flush();
                flush();
            });
            // 确保所有缓冲区都被刷新
            ob_end_flush();

            // 保存前双重保障数据库连接
            try {
                \think\Db::connect()->query('SELECT 1');
            } catch (\Exception $e) {
                \think\Db::connect(true);
            }
            //不是会员扣减次数
            if (!$is_vip) {
                \app\model\User::where('id', $user_id)->update(['chat_count' => $user['chat_count'] - 1]);
            }
            // 保存AI消息
            ChatLog::addRecord($user_id, $uuid, $fullResponse, 'assistant', $chat_title);
        } catch (\Exception $e) {
            \think\Db::connect(true); // 异常时强制重连
            Logger::error('流式请求异常: ' . $e->getMessage());
            echo json_encode(['content' => '请求超时', 'event' => 'content']) . "\n\n";
        }
        exit;
    }

}
